package com.olive.filter;


import java.io.IOException;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;

import com.olive.constants.UserConstants;
import com.olive.entity.User;
import com.olive.handler.CommonLoginFailureHandler;
import com.olive.mapper.UserMapper;
import com.olive.service.UserService;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

@Component
public class SmsCodeValidateFilter extends OncePerRequestFilter {

	@Resource
	private StringRedisTemplate stringRedisTemplate;
	@Resource
	private CommonLoginFailureHandler commonLoginFailureHandler;
	@Resource
	private UserService userService;

	@Override
	protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
		if (CharSequenceUtil.equals("/smslogin", httpServletRequest.getRequestURI()) &&
				CharSequenceUtil.equalsIgnoreCase("post", httpServletRequest.getMethod())) {
			try {
				validated(new ServletWebRequest(httpServletRequest));
			} catch (SessionAuthenticationException e) {
			    //直接抛出相关异常
				commonLoginFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e);
			}
		}
		filterChain.doFilter(httpServletRequest, httpServletResponse);
	}

	private void validated(ServletWebRequest request) {
		String code = request.getRequest().getParameter("smsCode");
		String mobile = request.getRequest().getParameter("mobile");
		String smsCode = stringRedisTemplate.opsForValue().get(mobile + "_" + UserConstants.SMS_REDIS_KEY);
		if (StrUtil.isEmpty(code)) {
			throw new SessionAuthenticationException("验证码不能为空");
		}

		if (StrUtil.isEmpty(mobile)) {
			throw new SessionAuthenticationException("手机号不能为空");
		}

		if (StrUtil.isEmpty(smsCode)) {
			throw new SessionAuthenticationException("验证码不存在");
		}
		Long expire = stringRedisTemplate.getExpire(mobile + "_" + UserConstants.SMS_REDIS_KEY);
		if (expire <= 0) {
			//如果已过期，redis会删除key，此时getExpire返回-2,key已自动被redis删除
			throw new SessionAuthenticationException("验证码已过期");
		}
		if (!StrUtil.equals(code, smsCode)) {
			throw new SessionAuthenticationException("验证码不匹配");
		}
		User user = userService.findByMobile(mobile);
		if (ObjectUtil.isNull(user)) {
			throw new SessionAuthenticationException("该手机号未注册");
		}
		//验证完成后redis内部将Key删除
		stringRedisTemplate.delete(mobile + "_" + UserConstants.SMS_REDIS_KEY);

	}
}

